package com.jlf.core.engine.server.impl;

import com.jlf.core.annotation.server.add.AddPreProcessor;
import com.jlf.core.annotation.server.edit.EditPreProcessor;
import com.jlf.core.engine.domain.SchemaCriterionDO;
import com.jlf.core.engine.domain.SchemaFieldDO;
import com.jlf.core.engine.entity.criterion.AddCriterionWrapper;
import com.jlf.core.engine.entity.criterion.EditCriterionWrapper;
import com.jlf.core.engine.persistence.SchemaCriterionPersistence;
import com.jlf.core.engine.server.SchemaCriterionServer;
import com.jlf.core.error.Errors;
import com.jlf.core.output.ResultException;
import com.jlf.core.server.impl._SimpleServerImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 模型的查询条件的管理服务
 *
 * @author wujr
 * 2023/7/21
 * @version 1.0
 * 【变更历史】
 * [wujr 2023/7/21 1.0 新增]
 */
@Slf4j
public class SchemaCriterionServerImpl extends _SimpleServerImpl<SchemaCriterionDO> implements SchemaCriterionServer {
    public SchemaCriterionServerImpl(SchemaCriterionPersistence persistence) {
        super(persistence);
//        registerPreWrapperAddConsumer((w) -> this.preAddCheckField((AddCriterionWrapper)w), 0);
//        registerPreWrapperEditConsumer((w) -> this.preEditCheckField((EditCriterionWrapper)w), 0);
    }

    @AddPreProcessor(order = 1)
    public void preAddCheckField(AddCriterionWrapper wrapper) throws Exception{
        if (wrapper.getSchemaFields().size() > 1){
            // 多字段联合处理，则字段的数据类型要保持一致
            Map<Integer, List<SchemaFieldDO>> mapClassDataTypeOfFields = wrapper.getSchemaFields().stream().collect(Collectors.groupingBy(SchemaFieldDO::getClassDataType));
            if (mapClassDataTypeOfFields.size() > 1){
                log.info("新增模型的检索条件：{}，该条件为多字段联合检索，要求字段的数据类型保持一致", wrapper.getRecord().getCriterionCode());
                throw new ResultException(Errors.OBJECT_TYPE_CONVERT_UNSUPPORTED, "字段的数据类型不一致");
            }
        }
        wrapper.getRecord().setClassDataType(wrapper.getSchemaFields().get(0).getClassDataType());
    }
    @EditPreProcessor(order = 1)
    public void preEditCheckField(EditCriterionWrapper wrapper) throws Exception{
        if (wrapper.getSchemaFields().size() > 1){
            // 多字段联合处理，则字段的数据类型要保持一致
            Map<Integer, List<SchemaFieldDO>> mapClassDataTypeOfFields = wrapper.getSchemaFields().stream().collect(Collectors.groupingBy(SchemaFieldDO::getClassDataType));
            if (mapClassDataTypeOfFields.size() > 1){
                log.info("编辑模型的检索条件：{}，该条件为多字段联合检索，要求字段的数据类型保持一致", wrapper.getRecord().getCriterionCode());
                throw new ResultException(Errors.OBJECT_TYPE_CONVERT_UNSUPPORTED, "字段的数据类型不一致");
            }
        }
        wrapper.getRecord().setClassDataType(wrapper.getSchemaFields().get(0).getClassDataType());
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public void add(List<SchemaCriterionDO> records, List<SchemaFieldDO> schemaFields) throws Exception {
        Map<String, SchemaFieldDO> mapClassCodeOfFields = schemaFields.stream().collect(Collectors.toMap(SchemaFieldDO::getClassFieldCode, Function.identity()));
        for (SchemaCriterionDO record : records){
            String[] fieldCodes = StringUtils.split(record.getClassFieldCode(), ",");
            Integer dataType = null;
            for (String fieldCode : fieldCodes){
                SchemaFieldDO schemaField = mapClassCodeOfFields.get(fieldCode);
                if (dataType == null){
                    dataType = schemaField.getClassDataType();
                }else{
                    if (!dataType.equals(schemaField.getClassDataType())){
                        log.info("批量新增模型的检索条件：{}，该条件为多字段联合检索，要求字段的数据类型保持一致", record.getCriterionCode());
                        throw new ResultException(Errors.OBJECT_TYPE_CONVERT_UNSUPPORTED, "字段的数据类型不一致");
                    }
                }
                record.setClassDataType(dataType);
            }
        }
        persistence().saveBatch(records);
    }
}
